#include "device_communication.grpc.pb.h"
#include <chrono>
#include <grpcpp/grpcpp.h>
#include <iostream>
#include <random>
#include <string>

using device_communication::DeviceInfoRequest;
using device_communication::DeviceInfoResponse;
using device_communication::DeviceService;
using device_communication::PingRequest;
using device_communication::PongResponse;
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;

// PC客户端类
class PCDeviceClient {
public:
  PCDeviceClient(std::shared_ptr<Channel> channel)
      : stub_(DeviceService::NewStub(channel)) {
    // 生成客户端唯一ID
    GenerateClientId();
  }

  // 发送Ping请求
  bool SendPing(std::string &serverResponse) {
    PingRequest request;
    PongResponse response;
    ClientContext context;

    // 设置请求参数
    request.set_client_id(clientId_);
    request.set_timestamp(GetCurrentTimestamp());

    // 发送gRPC请求（超时5秒）
    context.set_deadline(std::chrono::system_clock::now() +
                         std::chrono::seconds(5));
    Status status = stub_->Ping(&context, request, &response);

    // 处理响应
    if (status.ok()) {
      std::stringstream ss;
      ss << "Ping Response: " << std::endl
         << "  Success: " << (response.success() ? "Yes" : "No") << std::endl
         << "  Server ID: " << response.server_id() << std::endl
         << "  Timestamp: " << response.timestamp() << std::endl
         << "  Message: " << response.message();
      serverResponse = ss.str();
      return true;
    } else {
      serverResponse = "Ping Failed: " + status.error_message() +
                       " (code: " + std::to_string(status.error_code()) + ")";
      return false;
    }
  }

  // 获取设备信息
  bool GetDeviceInfo(std::string &deviceInfo) {
    DeviceInfoRequest request;
    DeviceInfoResponse response;
    ClientContext context;

    context.set_deadline(std::chrono::system_clock::now() +
                         std::chrono::seconds(5));
    Status status = stub_->GetDeviceInfo(&context, request, &response);

    if (status.ok()) {
      std::stringstream ss;
      ss << "Device Info: " << std::endl
         << "  Platform: " << response.platform() << std::endl
         << "  Model: " << response.device_model() << std::endl
         << "  System Version: " << response.system_version();
      deviceInfo = ss.str();
      return true;
    } else {
      deviceInfo = "Get Device Info Failed: " + status.error_message() +
                   " (code: " + std::to_string(status.error_code()) + ")";
      return false;
    }
  }

  // 获取客户端ID
  std::string GetClientId() const { return clientId_; }

private:
  // 生成客户端唯一ID
  void GenerateClientId() {
    auto now = std::chrono::system_clock::now();
    auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
                         now.time_since_epoch())
                         .count();

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1000, 9999);

    std::stringstream ss;
    ss << "client-" << timestamp << "-" << dis(gen);
    clientId_ = ss.str();
  }

  // 获取当前时间戳
  std::string GetCurrentTimestamp() {
    auto now = std::chrono::system_clock::now();
    auto in_time_t = std::chrono::system_clock::to_time_t(now);

    std::stringstream ss;
    ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %H:%M:%S");
    return ss.str();
  }

  std::unique_ptr<DeviceService::Stub> stub_; // gRPC客户端存根
  std::string clientId_;                      // 客户端唯一ID
};

int main(int argc, char **argv) {
  if (argc != 3) {
    std::cerr << "Usage: " << argv[0] << " <server_ip> <server_port>"
              << std::endl;
    std::cerr << "Example: " << argv[0] << " 192.168.1.100 50051" << std::endl;
    return 1;
  }

  std::string serverAddress = argv[1] + std::string(":") + argv[2];
  std::cout << "PC Client started. Connecting to server: " << serverAddress
            << std::endl;

  PCDeviceClient client(
      grpc::CreateChannel(serverAddress, grpc::InsecureChannelCredentials()));

  std::cout << "Client ID: " << client.GetClientId() << std::endl;
  std::cout << "Enter command (ping/info/exit): ";

  std::string command;
  while (std::getline(std::cin, command)) {
    if (command == "ping") {
      std::string response;
      if (client.SendPing(response)) {
        std::cout << "[SUCCESS] " << response << std::endl;
      } else {
        std::cerr << "[ERROR] " << response << std::endl;
      }
    } else if (command == "info") {
      std::string deviceInfo;
      if (client.GetDeviceInfo(deviceInfo)) {
        std::cout << "[SUCCESS] " << deviceInfo << std::endl;
      } else {
        std::cerr << "[ERROR] " << deviceInfo << std::endl;
      }
    } else if (command == "exit") {
      std::cout << "Exiting client..." << std::endl;
      break;
    } else {
      std::cout << "Unknown command. Supported commands: ping/info/exit"
                << std::endl;
    }
    std::cout << "Enter command (ping/info/exit): ";
  }
  return 0;
}
